package com.hly.tool.tree;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 数据层级类型
 * 层级
 * 1
 * 1.1
 * 1.1.1
 * 1.1.2
 * 1.2
 * 1.2.1
 * 1.2.1.1
 * 1.3
 * 2
 * 2.1
 * 2.2
 * 2.3
 *
 * @Auther: Jack.Hao
 * @Date: 2021/5/5 20:01
 * @Description:
 */
public class Tree2 {

    /**
     * 获取树结构 json 数据
     * @param lists
     * @return
     */
    public static JSONArray getTreeJSONArray (List<List> lists,String levelColumn) throws Exception {

        JSONArray array = new JSONArray();
        for (int i = 0; i <lists.size() ; i++) {
            List list = lists.get(i);
            String oneTree = getOneTree(list,levelColumn);
//            System.out.println("oneTree = "+oneTree);
            array.add(oneTree);
        }
        return array;
    }


    /**
     * 获取树结构 json 数据
     * @param lists
     * @return
     */
    public static String getTreeStr (List<List> lists, String levelColumn) throws Exception {
        return  getTreeJSONArray(lists,  levelColumn).toJSONString();
    }


    /**
     *
     * @param list
     * @return
     */
    private static String getOneTree(List list,String levelColumn) throws Exception {
        String tree = getTree(list,levelColumn);
        return tree;
    }


    /**
     * 获取树结构 json 数据
     * @param mapList
     * @return
     * @throws Exception
     */
    private  static  String getTree(List<Map<String,String>> mapList,String levelColumn) throws Exception {
//        数据分组
        Map<Integer, List<Map<String, String>>> groupMap = getGroupData(mapList,levelColumn);
//        获取数据分组后的key 集合
        Set<Integer> keySet = groupMap.keySet();
        List<Integer> keyList = new ArrayList<Integer>(keySet);
        keyList = keyList.stream().sorted((a, b) -> a - b).collect(Collectors.toList());
        String dataStr = null;
        if (groupMap == null) {
            return null;
        } else {
            dataStr = getLevelDataByGroupMap(groupMap,levelColumn);
        }
        return  dataStr;
    }






    /**
     * 数据分组
     *
     * @param mapList
     * @return
     */
    private static Map<Integer, List<Map<String, String>>> getGroupData(List<Map<String,String>> mapList,String levelColumn) {
        if (mapList == null || mapList.size() == 0) {
            return null;
        }

        Map<Integer, List<Map<String, String>>> groupMap = new HashMap<Integer, List<Map<String, String>>>();

        if (mapList == null || mapList.size() == 0) {
            return groupMap;
        }


        TreeSet<Integer> indexSet = new TreeSet<Integer>();
        for (int i = 0; i < mapList.size(); i++) {
            Map map_i = (Map) mapList.get(i);
            String level = (String) map_i.get(levelColumn);
//            indexSet.add(level.length());
            String[] split_i = level.split("\\.");
            indexSet.add(split_i.length);
        }

        for (int len : indexSet) {
            List<Map<String, String>> levelList = new ArrayList<Map<String, String>>();
            for (int i = 0; i < mapList.size(); i++) {
                Map map_i = (Map) mapList.get(i);
                String level = (String) map_i.get(levelColumn);
//                if (level.length() == len) {
//                    levelList.add(map_i);
//                }
                String[] split_i = level.split("\\.");
                if (split_i.length == len) {
                    levelList.add(map_i);
                }
            }
            groupMap.put(len, levelList);
        }

        return groupMap;
    }






    /**
     *
     * @param groupMap
     * @throws Exception
     */
    private static String getLevelDataByGroupMap(Map<Integer, List<Map<String, String>>> groupMap,String levelColumn) throws Exception {
        JSONArray array = new JSONArray();
        Set<Integer> keySet = groupMap.keySet();
        List<Integer> keyList = new ArrayList<Integer>(keySet);
//        JDK 1.7 not support
        keyList = keyList.stream().sorted((a, b) -> a - b).collect(Collectors.toList());
        String levelData = getLevelData(groupMap, keyList, array, null,levelColumn);
        return levelData;
    }

    /**
     * @param groupMap
     * @param keyList
     * @param array
     * @param jsonObject
     * @return
     * @throws Exception
     */
    private  static  String getLevelData(Map<Integer, List<Map<String, String>>> groupMap, List<Integer> keyList, JSONArray array, JSONObject jsonObject,String levelColumn) throws Exception {

        int key = 0;
        String level = null;

        if (jsonObject == null) {
            key = keyList.get(0);
        } else {
            level = jsonObject.getString(levelColumn);
//            key = level.length() + 2;
            String[] split = level.split("\\.");
            key = split.length + 1;
        }

        List<Map<String, String>> maps = groupMap.get(key);

        if (maps == null || maps.size() == 0) {
            jsonObject.put("children", new JSONArray());
            return array.toString();
        }

        if (jsonObject == null) {
            for (int i = 0; i < maps.size(); i++) {
                Map<String, String> map_i = maps.get(i);
                String jsonStr_i = JSONObject.toJSONString(map_i);
                JSONObject  json_i = JSONObject.parseObject(jsonStr_i);
                array.add(json_i);
                getLevelData(groupMap, keyList, array, json_i,levelColumn);
            }
        } else {
            JSONArray carray = new JSONArray();
            for (int i = 0; i < maps.size(); i++) {
                Map<String, String> map_i = maps.get(i);
                String clevel = map_i.get(levelColumn);
                if (clevel.startsWith(level+".")) {
                    String jsonStr_i = JSONObject.toJSONString(map_i);
                    JSONObject  json_i = JSONObject.parseObject(jsonStr_i);
                    carray.add(json_i);
                    getLevelData(groupMap, keyList, carray, json_i,levelColumn);
                }
            }
            jsonObject.put("children", carray);
        }
        return array.toString();
    }


}
